/***********************************************
 @Name :        小铭同学
 @Time :        2025-09-03
 @Email :       LiaoMingWJ233@163.com
 @Comment :     自定义控件 天气预报信息类 高温曲线图
 @FileName :    weatherchart.cpp
 @Version :     1.0
************************************************/


#include "weatherchart.h"

WeatherChart::WeatherChart(QWidget *parent) : QWidget(parent)
{
    // 设置固定大小
    setFixedSize(CHART_WIDTH, CHART_HEIGHT);
    // 设置背景透明
    setAttribute(Qt::WA_TranslucentBackground);
    
    setFixedHeight(100); // 固定高度为100
}

void WeatherChart::setForecastData(const QList<Forecast> &forecastList)
{
    if(forecastList.size() < 7) {
        qDebug() << "天气数据不足7天";
        return;
    }
    
    // 提取温度和日期数据
    for(int i = 0; i < 7; ++i) {
        const Forecast &f = forecastList[i];
        
        // 使用正则表达式提取高温数值
        QRegExp highRegExp("(\\d+)");
        if(highRegExp.indexIn(f.high) != -1) {
            highTemp[i] = highRegExp.cap(1).toDouble();
        } else {
            highTemp[i] = 0;
            qDebug() << "无法解析高温数据:" << f.high;
        }
        
        // 使用正则表达式提取低温数值
        QRegExp lowRegExp("(\\d+)");
        if(lowRegExp.indexIn(f.low) != -1) {
            lowTemp[i] = lowRegExp.cap(1).toDouble();
        } else {
            lowTemp[i] = 0;
            qDebug() << "无法解析低温数据:" << f.low;
        }
        
        // 从"2025-07-28"中提取"28日"
        QStringList dateParts = f.ymd.split('-');
        if(dateParts.size() == 3) {
            days[i] = dateParts[2] + "日";
        } else {
            days[i] = QString::number(i+1) + "日";
        }
    }
    
    update(); // 触发重绘
}

void WeatherChart::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);
    
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    
    // 计算绘制区域（总高度100px）
    const int paddingTop = 5;    // 顶部留白
    const int paddingBottom = 20; // 底部留白（给日期文字）
    const int chartHeight = 75;   // 实际曲线区域高度
    
    QRect chartRect(0, paddingTop, width(), chartHeight);
    
    // 计算温度范围（自动调整）
    double minTemp, maxTemp;
    calculateYRange(minTemp, maxTemp);
    
    // 绘制温度曲线（限制在chartHeight内）
    drawTemperatureCurve(painter, chartRect, minTemp, maxTemp);
    
    // 绘制底部日期（在paddingBottom区域内）
    drawDateLabels(painter, QRect(0, paddingTop + chartHeight, width(), paddingBottom));
}


void WeatherChart::calculateYRange(double &min, double &max)
{
    // 初始化最小最大值
    min = highTemp[0];
    max = highTemp[0];
    
    // 找出7天中的高温-最低温和最高温
    for(int i = 1; i < 7; ++i) {
        if(highTemp[i] < min) min = highTemp[i];
        if(highTemp[i] > max) max = highTemp[i];
    }
    
    // 扩大一点范围使曲线不会贴着边缘
    double range = max - min;
    min -= range * 0.8;
    max += range * 0.8;
}

void WeatherChart::drawAxes(QPainter &painter, const QRect &chartRect)
{
    painter.save();
    
    QPen axisPen(Qt::black);
    axisPen.setWidth(1);
    painter.setPen(axisPen);
    
    // 绘制横轴(底部)
    painter.drawLine(chartRect.left(), chartRect.bottom(), 
                    chartRect.right(), chartRect.bottom());
    
    // 绘制横坐标刻度(日期)
    QFont font = painter.font();
    font.setPointSize(8);
    painter.setFont(font);
    
    int dayWidth = chartRect.width() / 7;
    for(int i = 0; i < 7; ++i) {
        int x = chartRect.left() + i * dayWidth + dayWidth/2;
        QRect textRect(x - 30, chartRect.bottom() + 5, 60, 20);
        painter.drawText(textRect, Qt::AlignCenter, days[i]);
    }
    
    painter.restore();
}

void WeatherChart::drawTemperatureCurve(QPainter &painter, const QRect &chartRect, double minTemp, double maxTemp)
{
    painter.save();
    
    // 计算缩放比例（确保所有内容在chartHeight内）
    double tempRange = maxTemp - minTemp;
    double yScale = chartRect.height() / tempRange;
    
    int dayWidth = chartRect.width() / 7;
    
    // 绘制曲线路径
    QPainterPath curvePath;
    QPainterPath fillPath;
    
    // 第一个点
    int firstX = chartRect.left() + dayWidth/2;
    double firstY = chartRect.bottom() - (highTemp[0] - minTemp) * yScale;
    curvePath.moveTo(firstX, firstY);
    fillPath.moveTo(firstX, chartRect.bottom());
    fillPath.lineTo(firstX, firstY);
    
    // 中间点
    for(int i = 1; i < 7; ++i) {
        int x = chartRect.left() + i * dayWidth + dayWidth/2;
        double y = chartRect.bottom() - (highTemp[i] - minTemp) * yScale;
        
        // 贝塞尔曲线控制点
        int prevX = chartRect.left() + (i-1) * dayWidth + dayWidth/2;
        double prevY = chartRect.bottom() - (highTemp[i-1] - minTemp) * yScale;
        
        curvePath.cubicTo(prevX + dayWidth/3, prevY, 
                         x - dayWidth/3, y, 
                         x, y);
        fillPath.cubicTo(prevX + dayWidth/3, prevY, 
                        x - dayWidth/3, y, 
                        x, y);
    }
    
    // 填充曲线下方
    fillPath.lineTo(chartRect.left() + 6*dayWidth + dayWidth/2, chartRect.bottom());
    painter.fillPath(fillPath, QColor(175, 238, 238));
    
    // 绘制曲线
    painter.setPen(QPen(QColor(138, 43, 226), 2));
    painter.drawPath(curvePath);
    
    // 绘制温度点和标签（确保在chartRect内）
    QFont font = painter.font();
    font.setPixelSize(10); // 使用像素单位更精确控制
    painter.setFont(font);
    
    // 定义蓝紫色常量
    const QColor textColor(138, 43, 226); // 蓝紫色文字 
    
    for(int i = 0; i < 7; ++i) {
        int x = chartRect.left() + i * dayWidth + dayWidth/2;
        double y = chartRect.bottom() - (highTemp[i] - minTemp) * yScale;
        
        // 确保锚点位置有效
        y = qBound(chartRect.top() + 5.0, y, chartRect.bottom() - 5.0);
        
        // 绘制锚点
        painter.setBrush(QColor(138, 43, 226));
        painter.drawEllipse(QPointF(x, y), 3, 3);
                    
        // 绘制温度文本（确保在chartRect内）
        QString tempText = QString::number(highTemp[i]) + "°";
        QRect textRect(x - 15, y - 20, 30, 15); // 上移20px                 
        
        // 如果超出顶部，改为向下显示
        if(textRect.top() < chartRect.top()) {
            textRect.moveTop(y + 5);
        }       
        // 设置文字颜色
        painter.setPen(textColor);
        painter.drawText(textRect, Qt::AlignCenter, tempText);
    }
    
    painter.restore();
}

void WeatherChart::drawDateLabels(QPainter &painter, const QRect &dateRect)
{
    painter.save();
    
    // 设置蓝紫色文字
    painter.setPen(QColor(138, 43, 226));
    QFont font = painter.font();
    font.setPixelSize(10); // 小字号确保不超出区域
    painter.setFont(font);
    
    int dayWidth = width() / 7;
    for(int i = 0; i < 7; ++i) {
        int x = dayWidth * i + dayWidth/2;
        QRect textRect(x - 25, dateRect.top(), 50, dateRect.height());
        painter.drawText(textRect, Qt::AlignCenter, days[i]);
    }
    
    painter.restore();
}
